发布于 

Equivalent Prefixes [笛卡尔树]

Equivalent Prefixes [笛卡尔树]

2019牛客多校 第一场 A

题目来源:Nowcoder

分析

题目给定了a[],b[],要求找出最大的\(p \leq n\)满足\([a_1, a_2, ... , a_p]\)\([b_1, b_2, ... ,b_p]\)是“相等”的。相等在这个题目中的定义为:对于长度都为n的序列u[]v[],任意的\(1 \leq 1 \leq l \leq r \leq n\)都能使\(RMQ(u, l, r) = RMQ(v, l, r)\)\(RMQ()\)即为区间最小值的下标。

我们先来研究如何判断两个序列是“相等”的。很明显,由于对于任意的\(l\)\(r\)\(RMQ(l,r)\)都相同,那么这两个序列中每个数的相对顺序都是一样的。其实,这也就代表着,这两个序列构造出的笛卡尔树的结构是相同的。

但是,答案要求的是“最小的满足条件的\(p\)”。如果我们每次都对笛卡尔树的结构做一次比较的话,由于每次要比较所有的点,所以时间为\(O(n^2)\),肯定超时了。那么,还有什么能够让我们确定这两个笛卡尔树相同呢?笛卡尔树构造中的单调栈。单调栈能够唯一地反映当前插入的点的位置,只要每次的单调栈相同,那么生成的笛卡尔树一定相同。而且实际上,由于单调栈的长度变化能唯一的反映出插入点位置的变化,所以只需要每次比较单调栈的长度即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <iostream>
#include <algorithm>
#include <stack>

#define L 0
#define R 1
#define MAXN 100100

using namespace std;

struct Node
{
int val;
Node *fa;
Node *son[2];

Node(int val = 0)
{
this->val = val;
fa = NULL;
son[L] = NULL;
son[R] = NULL;
}
};

struct CartesianTree
{
stack<Node *> s;
Node *root;

CartesianTree()
{
root = NULL;
s = stack<Node *>();
}

void insert(int a)
{
Node *next = new Node(a);
Node *last = NULL;

while (!s.empty())
{
if (s.top()->val < next->val)
{
Node *tmp = s.top();
if (tmp->son[R])
tmp->son[R]->fa = next;
next->son[L] = tmp->son[R];
tmp->son[R] = next;
next->fa = tmp;
break;
}
last = s.top();
s.pop();
}

if (s.empty() && last)
{
next->son[L] = last;
last->fa = next;

if (last==root)
root = next;
}
if (root==NULL)
root = next;

s.push(next);
}
};

int a[MAXN], b[MAXN];

int main()
{
ios::sync_with_stdio(false);

int n;

while (cin>>n)
{
for (int i = 0; i<n; i++)
cin >> a[i];
for (int i = 0; i<n; i++)
cin >> b[i];

CartesianTree x, y;

int i;
for (i = 0; i<n; i++)
{
x.insert(a[i]);
y.insert(b[i]);

if (x.s.size() != y.s.size())
break;
}

cout << i << endl;
}
}

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 [@Songer](https://blog.songer.xyz/) 创建,使用 Stellar 作为主题。